{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "#-*- coding: utf-8 -*-"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 类的三要素：类名、属性、方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#类是对象的载体，我们可以把一类对象的公共特征抽象出来，创建通用的类\n",
    "#创建类\n",
    "class Cat():\n",
    "    \"\"\"模拟篇\"\"\"\n",
    "    def __init__(self,name):\n",
    "        \"\"\"初始化属性\"\"\"\n",
    "        self.name = name\n",
    "    def jump(self):\n",
    "        \"\"\"模拟猫的跳跃\"\"\"\n",
    "        print(self.name+\" is jumping\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "#用类创建实例\n",
    "my_cat = Cat(\"Loser\")\n",
    "your_cat = Cat(\"Lucky\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loser\n",
      "Lucky\n"
     ]
    }
   ],
   "source": [
    "#调用属性\n",
    "print(my_cat.name)\n",
    "print(your_cat.name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Loser is jumping\n",
      "Lucky is jumping\n"
     ]
    }
   ],
   "source": [
    "#调用方法\n",
    "my_cat.jump()\n",
    "your_cat.jump()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 类的命名"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "#类的命名要有实际意义 采用驼峰命名法，即组成的单词首字母大写\n",
    "#类的属性\n",
    "#def __init__(self,要传递的参数）  初始化类的操作\n",
    "#无论是初始化类还是定义方法的时候，都需要有self参数\n",
    "class Car():\n",
    "    \"\"\"模拟汽车\"\"\"\n",
    "\n",
    "    def __init__(self,brand,model,year):\n",
    "        \"\"\"初始化汽车属性\"\"\"         #相当于类内部的变量\n",
    "        self.brand = brand\n",
    "        self.model = model\n",
    "        self.year = year\n",
    "        self.mileage = 0   #新车总里程初始化为0\n",
    "\n",
    "    def get_main_infomation(self):  #self不能省略\n",
    "        \"\"\"获取汽车的主要信息\"\"\"\n",
    "        print(\"品牌：{} 型号：{} 出厂年份：{}\".format(self.brand,self.model,self.year))\n",
    "\n",
    "    def get_mileage(self):\n",
    "        \"\"\"获取总里程数\"\"\"\n",
    "        return \"汽车行驶总里程：{}公里\".format(self.mileage)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 创建实例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "#创建实例  将实例赋值给对象，实例化过程中，传入相应的参数 v = 类名（必要的初始化参数）\n",
    "my_new_car = Car(\"Audi\",\"A6\",\"2018\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Audi\n",
      "A6\n",
      "0\n"
     ]
    }
   ],
   "source": [
    "#访问属性  类名.类属性\n",
    "print(my_new_car.brand)\n",
    "print(my_new_car.model)\n",
    "print(my_new_car.mileage)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "品牌：Audi 型号：A6 出厂年份：2018\n",
      "汽车行驶总里程：0公里\n"
     ]
    }
   ],
   "source": [
    "#方法调用  实例名.方法名（必要的参数）\n",
    "my_new_car = Car(\"Audi\",\"A6\",\"2018\")\n",
    "my_new_car.get_main_infomation()\n",
    "s = my_new_car.get_mileage()\n",
    "print (s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "12000\n"
     ]
    }
   ],
   "source": [
    "#属性修改\n",
    "#直接修改 先访问 后修改\n",
    "my_new_car = Car(\"BYD\",\"宋\",2016)\n",
    "my_new_car.mileage = 12000\n",
    "print(my_new_car.mileage)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "#通过方法修改属性\n",
    "class Car1():\n",
    "    \"\"\"模拟汽车\"\"\"\n",
    "\n",
    "    def __init__(self,brand,model,year,distance):\n",
    "        \"\"\"初始化汽车属性\"\"\"         #相当于类内部的变量\n",
    "        self.brand = brand\n",
    "        self.model = model\n",
    "        self.year = year\n",
    "        self.mileage = 0   #新车总里程初始化为0\n",
    "\n",
    "    def get_main_infomation(self):  #self不能省略\n",
    "        \"\"\"获取汽车的主要信息\"\"\"\n",
    "        print(\"品牌：{} 型号：{} 出厂年份：{}\".format(self.brand,self.model,self.year))\n",
    "\n",
    "    def get_mileage(self):\n",
    "        \"\"\"获取总里程数\"\"\"\n",
    "        return \"汽车行驶总里程：{}公里\".format(self.mileage)\n",
    "    def set_mileage(self,distance):\n",
    "        \"\"\"设置总里程数\"\"\"\n",
    "        self.mileage = distance"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 类的继承"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "#所谓继承，就是底层级的抽象继承高层级的抽象的过程\n",
    "#简单的继承\n",
    "#父类\n",
    "\n",
    "class Car():\n",
    "    \"\"\"模拟汽车\"\"\"\n",
    "\n",
    "    def __init__(self,brand,model,year):\n",
    "        \"\"\"初始化汽车属性\"\"\"         #相当于类内部的变量\n",
    "        self.brand = brand\n",
    "        self.model = model\n",
    "        self.year = year\n",
    "        self.mileage = 0   #新车总里程初始化为0\n",
    "\n",
    "    def get_main_infomation(self):  #self不能省略\n",
    "        \"\"\"获取汽车的主要信息\"\"\"\n",
    "        print(\"品牌：{} 型号：{} 出厂年份：{}\".format(self.brand,self.model,self.year))\n",
    "\n",
    "    def get_mileage(self):\n",
    "        \"\"\"获取总里程数\"\"\"\n",
    "        return \"汽车行驶总里程：{}公里\".format(self.mileage)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "#构造电动汽车子类  class 子类名（父类名）：\n",
    "class ElectricCar(Car):\n",
    "    \"模拟电动汽车\"\n",
    "\n",
    "    def __init__(self,brand,model,year):\n",
    "        \"\"\"初始化电动汽车属性\"\"\"\n",
    "        #声明继承父类的属性,此时子类自动继承父类方法\n",
    "        super().__init__(brand,model,year) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "品牌：NextWeek 型号：FF91 出厂年份：2046\n"
     ]
    }
   ],
   "source": [
    "#使用子类\n",
    "my_electric_car = ElectricCar(\"NextWeek\",\"FF91\",2046)\n",
    "my_electric_car.get_main_infomation()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "#给子类添加属性和方法\n",
    "class ElectricCar1(Car):\n",
    "    \"\"\"模拟电动汽车\"\"\"\n",
    "    #新传入电池容量数据\n",
    "    def __init__(self,brand,model,year,bettery_size):\n",
    "        super().__init__(brand,model,year) #声明继承父类的属性,此时子类自动继承父类方法\n",
    "        self.bettery_size = bettery_size #电池容量\n",
    "        self.electric_quantity = bettery_size #电池剩余容量\n",
    "        self.electric2distance_ratio = 5 #电池距离换算系数\n",
    "        self.remainder_range = self.electric_quantity*self.electric2distance_ratio   #剩余可行驶旅程\n",
    "\n",
    "    def get_electric_quantity(self):\n",
    "        \"\"\"查看当前电池容量\"\"\"\n",
    "        print(\"当前电池剩余电量:{} kw.h\".format(self.electric_quantity))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当前电池剩余电量:70 kw.h\n"
     ]
    }
   ],
   "source": [
    "#使用子类\n",
    "my_electric_car = ElectricCar1(\"NewWeek\",\"FF91\",2046,70)\n",
    "my_electric_car.get_electric_quantity()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "#重写父类的方法--多态  同样的方法 在不同的子类里面有不同的表达方式\n",
    "class ElectricCar2(Car):\n",
    "    \"\"\"模拟电动汽车\"\"\"\n",
    "    #新传入电池容量数据\n",
    "    def __init__(self,brand,model,year,bettery_size):\n",
    "        super().__init__(brand,model,year) #声明继承父类的属性,此时子类自动继承父类方法\n",
    "        self.bettery_size = bettery_size #电池容量\n",
    "        self.electric_quantity = bettery_size #电池剩余容量\n",
    "        self.electric2distance_ratio = 5 #电池距离换算系数\n",
    "        self.remainder_range = self.electric_quantity*self.electric2distance_ratio   #剩余可行驶旅程\n",
    "\n",
    "    def get_main_infomation(self):    #重写父类方法\n",
    "        \"\"\"获取汽车主要信息\"\"\"\n",
    "        print(\"品牌：{} 型号：{} 出厂年份：{} 续航里航：{}公里\"\n",
    "              .format(self.brand,self.model,self.year,self.bettery_size*self.electric2distance_ratio))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "品牌：NextWeek 型号：FF91 出厂年份：2046 续航里航：350公里\n"
     ]
    }
   ],
   "source": [
    "#调用\n",
    "my_electric_car = ElectricCar2(\"NextWeek\",\"FF91\",2046,70)\n",
    "my_electric_car.get_main_infomation()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "#用在类中的实例 把电池抽象成一个对象 逻辑更加清晰\n",
    "class Bettery():\n",
    "    \"\"\"模拟电动汽车的电池\"\"\"\n",
    "    def __init__(self,bettery_size = 70):\n",
    "        self.bettery_size = bettery_size  # 电池容量\n",
    "        self.electric_quantity = bettery_size  # 电池剩余容量\n",
    "        self.electric2distance_ratio = 5  # 电池距离换算系数\n",
    "        self.remainder_range = self.electric_quantity * self.electric2distance_ratio  # 剩余可行驶旅程\n",
    "\n",
    "    def get_electric_quantity(self):\n",
    "        \"\"\"查看当前电池容量\"\"\"\n",
    "        print(\"当前电池剩余电量:{} kw.h\".format(self.electric_quantity))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "品牌：NextWeek 型号：FF91 出厂年份：2046 续航里航：350公里\n"
     ]
    }
   ],
   "source": [
    "#重新构造电动汽车类 使模块更加清晰\n",
    "class ElectricCar4(Car):\n",
    "    \"\"\"模拟电动汽车\"\"\"\n",
    "\n",
    "    def __init__(self,brand,model,year,bettery_size):\n",
    "        \"\"\"初始化电动汽车属性\"\"\"\n",
    "        super().__init__(brand,model,year) #声明继承父类的属性,此时子类自动继承父类方法\n",
    "        self.bettery = Bettery(bettery_size) #创建电池实例，并且把这个属性赋值给bettery\n",
    "\n",
    "    def get_main_infomation(self):\n",
    "        \"\"\"获取汽车主要信息\"\"\"\n",
    "        print(\"品牌：{} 型号：{} 出厂年份：{} 续航里航：{}公里\"\n",
    "              .format(self.brand, self.model, self.year, \n",
    "                      self.bettery.bettery_size * self.bettery.electric2distance_ratio))\n",
    "#调用\n",
    "my_electric_car = ElectricCar2(\"NextWeek\",\"FF91\",2046,70)\n",
    "my_electric_car.get_main_infomation()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Python super 详解"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "#https://www.runoob.com/w3cnote/python-super-detail-intro.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 约定"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 默认， Python 3\n",
    "class A:\n",
    "    pass\n",
    "\n",
    "# Python 2\n",
    "class A(object):\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 默认，Python 3\n",
    "class B(A):\n",
    "    def add(self, x):\n",
    "        super().add(x)\n",
    "\n",
    "# Python 2\n",
    "#所以，你如果用的是 Python 2 的话，记得将本文的 super() 替换为 suepr(Class, self) 。\n",
    "class B(A):\n",
    "    def add(self, x):\n",
    "        super(B, self).add(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 单继承"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "#在单继承中 super 就像大家所想的那样，主要是用来调用父类的方法的。\n",
    "class A:\n",
    "    def __init__(self):\n",
    "        self.n = 2\n",
    "\n",
    "    def add(self, m):\n",
    "        print('self is {0} @A.add'.format(self))\n",
    "        self.n += m\n",
    "\n",
    "\n",
    "class B(A):\n",
    "    def __init__(self):\n",
    "        self.n = 3\n",
    "\n",
    "    def add(self, m):\n",
    "        print('self is {0} @B.add'.format(self))\n",
    "        super().add(m)\n",
    "        self.n += 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "self is <__main__.B object at 0x10c91bac8> @B.add\n",
      "self is <__main__.B object at 0x10c91bac8> @A.add\n",
      "8\n"
     ]
    }
   ],
   "source": [
    "b = B()\n",
    "b.add(2)\n",
    "print(b.n)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 多继承"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "class C(A):\n",
    "    def __init__(self):\n",
    "        self.n = 4\n",
    "\n",
    "    def add(self, m):\n",
    "        print('self is {0} @C.add'.format(self))\n",
    "        super().add(m)\n",
    "        self.n += 4\n",
    "\n",
    "\n",
    "class D(B, C):\n",
    "    def __init__(self):\n",
    "        self.n = 5\n",
    "\n",
    "    def add(self, m):\n",
    "        print('self is {0} @D.add'.format(self))\n",
    "        super().add(m)\n",
    "        self.n += 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "self is <__main__.D object at 0x10c939eb8> @D.add\n",
      "self is <__main__.D object at 0x10c939eb8> @B.add\n",
      "self is <__main__.D object at 0x10c939eb8> @C.add\n",
      "self is <__main__.D object at 0x10c939eb8> @A.add\n",
      "19\n"
     ]
    }
   ],
   "source": [
    "d = D()\n",
    "d.add(2)\n",
    "print(d.n)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# super 是个类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
